#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <assert.h>
#include "ff_api.h"
#include "ff_config.h"

#define SERVPORT 3333 /* 定义端口号 */
#define BACKLOG 10    /* 定义最大连接数量 */

#define MAX_EVENTS 10

/* kevent set */
struct kevent kevSet;
/* events */
struct kevent events[MAX_EVENTS];
/* kq */
int loop(void *arg);
int kq;
int sockfd;
int client_fd; /* sockfd:监听socket ,clientfd用于数据传输 */
int sin_size;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;

int main(int argc, char *argv[])
{
    ff_init(argc, argv);
    printf("initialized succeed!\n");    
   
    

    if ((sockfd = ff_socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket创建失败！");
        exit(1);
    }

    printf("socket created succeed!\n");    
    /* 设置套接字信息 */
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(SERVPORT); /* htons() 函数把主机字节序转换成网络字节序 */
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    bzero(&(my_addr.sin_zero), 8);

    /* 绑定端口 */
    if (ff_bind(sockfd, (struct linux_sockaddr *)&my_addr, sizeof(my_addr)) == -1)
    {
        perror("bind出错");
        exit(1);
    }
    
     
    printf("binded succeed!\n");    
    /* 监听 */
    if (ff_listen(sockfd, BACKLOG) == -1)
    {
        perror("listen出错");
        exit(1);
    }
    
    printf("listen on %d\n",SERVPORT); 
      
    EV_SET(&kevSet, sockfd, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);

    assert((kq = ff_kqueue()) > 0);

    /* Update kqueue */
    ff_kevent(kq, &kevSet, 1, NULL, 0, NULL);
    printf("start run ...\n");
    ff_run(loop, NULL);

    return 0;
}

int loop(void *arg)
{
//    printf("start loop..\n");
    /* Wait for events to happen */
    unsigned nevents = ff_kevent(kq, NULL, 0, events, MAX_EVENTS, NULL);
    unsigned i;

    for (i = 0; i < nevents; ++i)
    {   
	printf("entering queue\n");
        struct kevent event = events[i];
        int clientfd = (int)event.ident;

        /* Handle disconnect */
        if (event.flags & EV_EOF)
        {
            /* Simply close socket */
            ff_close(clientfd);
        }
        else if (clientfd == sockfd)
        {
            int available = (int)event.data;
            do
            {
                int nclientfd = ff_accept(sockfd, NULL, NULL);
                if (nclientfd < 0)
                {
                    printf("ff_accept failed:%d, %s\n", errno,
                           strerror(errno));
                    break;
                }

                /* Add to event list */
                EV_SET(&kevSet, nclientfd, EVFILT_READ, EV_ADD, 0, 0, NULL);

                if (ff_kevent(kq, &kevSet, 1, NULL, 0, NULL) < 0)
                {
                    printf("ff_kevent error:%d, %s\n", errno,
                           strerror(errno));
                    return -1;
                }

                available--;
            } while (available);
        }
        else if (event.filter == EVFILT_READ)
        {
            // char buf[256];
            // size_t readlen = ff_read(clientfd, buf, sizeof(buf));

            // ff_write(clientfd, html, sizeof(html));
	    printf("wait to accept\n");
            while (1)
            {   
            //	printf("accept wait fot connection\n");
                sin_size = sizeof(struct sockaddr_in);
                if ((client_fd = ff_accept(sockfd, (struct linux_sockaddr *)&remote_addr, &sin_size)) == -1)
                {
                    perror("accept 出错！");
                    continue;
                }

                printf("收到一个连接来自： %s\n", inet_ntoa(remote_addr.sin_addr));
                if (!fork())
                {
                    /* 子进程代码段 */
                    if (ff_send(client_fd, "连接上了 \n", 26, 0) == -1)
                    {
                        perror("send出错");
                        ff_close(client_fd);
                        exit(0);
                    }
                }

                ff_close(client_fd);
            }
        }
        else
        {
            printf("unknown event: %8.8X\n", event.flags);
        }
    }
}
